package com.briup.corejava.day17;

/**
 * 线程通信：多个线程协作完成任务
 * 由锁对象调用下面三个方法
 * wait：当前线程进入等待阻塞，释放掉锁对象
 * notify：随机唤醒等待池中的一条线程
 * notifyAll：全部唤醒等待池中的所有线程
 */
public class Test2 {
    public static void main(String[] args) {
        // 实例化锁对象
        Plate plate = new Plate();
        // 创建线程
        Thread t1 = new Producer(plate,"厨师");
        Thread t2 = new Costumer(plate,"顾客1");
        Thread t3 = new Costumer2(plate,"顾客2");
        // 启动线程
        t1.start();
        t2.start();
        t3.start();
    }
}
// 锁对象
class Plate{
    // 计数的变量
    int num = 0;
    // 旗标
//    boolean flag = false; // 适用于两个线程
    int flag = 0; // 适用多个线程
}
// 生产者
class Producer extends Thread{
    // 维护锁对象
    private Plate plate;
    public Producer(Plate plate, String name){
        super(name);
        this.plate = plate;
    }
    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            // 定义同步代码块，对包子数量进行修改
            synchronized (plate){
                // 判断。有包子的时候不生产，让生产者进入等待
                while(plate.flag!=0){
                    try {
                        plate.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String name = Thread.currentThread().getName();
                // 如果没有包子，让包子数量+1
                System.out.println(name+"正在做第"+i+"次包子，每次2个");
                plate.num+=2;
                System.out.println("包子数量剩余：【"+plate.num+"】个");
                // 修改包子状态
                plate.flag = 1;
                // 通知消费者吃包子
                plate.notifyAll();
            }
        }
    }
}
// 消费者
class Costumer extends Thread{
    // 维护锁对象
    private Plate plate;
    public Costumer(Plate plate, String name){
        super(name);
        this.plate = plate;
    }
    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            // 定义同步代码块，对包子数量进行修改
            synchronized (plate){
                // 判断。没有包子的时候不吃，让消费者进入等待
                while(plate.flag!=1){
                    try {
                        plate.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String name = Thread.currentThread().getName();
                // 如果有包子，让包子数量-1
                System.out.println(name+"正在吃第"+i+"个包子");
                plate.num--;
                System.out.println("包子数量剩余：【"+plate.num+"】个");
                // 指引下一个运行的线程是谁
                plate.flag = 2;

                // 通知生产者做包子
                plate.notifyAll();
            }
        }
    }
}
// 消费者2
class Costumer2 extends Thread{
    // 维护锁对象
    private Plate plate;
    public Costumer2(Plate plate, String name){
        super(name);
        this.plate = plate;
    }
    @Override
    public void run() {
        for(int i=1;i<=100;i++){
            // 定义同步代码块，对包子数量进行修改
            synchronized (plate){
                // 判断。没有包子的时候不吃，让消费者进入等待
                while(plate.flag!=2){
                    try {
                        plate.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                String name = Thread.currentThread().getName();
                // 如果有包子，让包子数量-1
                System.out.println(name+"正在吃第"+i+"个包子");
                plate.num--;
                System.out.println("包子数量剩余：【"+plate.num+"】个");

                plate.flag = 0;
                // 通知生产者做包子
                plate.notifyAll();
            }
        }
    }
}
